package com.mobdev.notepad.shared.ui;

import android.app.ListActivity;
import android.content.ContentUris;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.FilterQueryProvider;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

import com.localytics.android.LocalyticsSession;
import com.mobdev.notepad.shared.DBConstants;
import com.mobdev.notepad.shared.NotepadStrings;
import com.mobdev.notepad.shared.UtilityMethods;

/**
 * Displays a list of notes. Will display notes from the {@link Uri}
 * provided in the intent if there is one, otherwise defaults to displaying the
 * contents of the {@link NotePadProvider}
 */
public abstract class AbstractNotesList extends ListActivity {
    private static final String TAG = "NotesList";

    // Menu item ids
    public static final int MENU_ITEM_DELETE = Menu.FIRST;
    public static final int MENU_ITEM_INSERT = Menu.FIRST + 1;
    public static final int MENU_ITEM_SYNC = Menu.FIRST + 2;
    public static final int MENU_ITEM_EDIT = Menu.FIRST + 3;
    public static final int MENU_ITEM_EDIT_TITLE = Menu.FIRST + 4;
    public static final int MENU_ITEM_SETTINGS = Menu.FIRST + 5;

    /**
     * The columns we are interested in from the database
     */
    private static final String[] PROJECTION = new String[]
    {
            DBConstants._ID, // 0
            DBConstants.TITLE, // 1
    };

    /** The index of the title column */
    private static final int COLUMN_INDEX_TITLE = 1;

	protected static final int REQUEST_CODE_PREFERENCES = 1;

	private LocalyticsSession localyticsSession;

	protected abstract void init();

	protected abstract int getNotesListItemId();

	protected abstract int getSyncMenuIconId();

	protected abstract void doEditNote(Uri mUri, String action);
	protected abstract void doSync();
	protected abstract void doPreferences();
	protected abstract void doEditTitle(Uri mUri);

	protected abstract String getLocalyticsAppKey();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setDefaultKeyMode(DEFAULT_KEYS_SHORTCUT);

        init();

        //------- LOCALYITCS -----
        // Instantiate the object
        this.localyticsSession = new LocalyticsSession(
                       this.getApplicationContext(),  // Context used to access device resources
                       getLocalyticsAppKey());   // Whether this is a new, or recreated activity

        this.localyticsSession.open();        // open the session
        this.localyticsSession.upload();      // upload any data
        this.localyticsSession.close();		  // close to persist session to disk



        // At this point, Localytics Initialization is done.  After uploads complete nothing
        // more will happen due to Localytics until the next time you call it.
        //------- LOCALYITCS -----



        // Inform the list we provide context menus for items
        ListView listView = getListView();
        listView.setOnCreateContextMenuListener(this);
        listView.setTextFilterEnabled(true);
    }

    /**
     * Refresh notes list
     */
    protected void updateList() {

		final String sortOrder;
		String sortOrderSetting = PreferenceManager.getDefaultSharedPreferences(this).getString("sort_order", null);
		if(sortOrderSetting != null && sortOrderSetting.equals("title")) {
			sortOrder = "title ASC";
		} else if(sortOrderSetting != null && sortOrderSetting.equals("modified_time")) {
			sortOrder = "modified_on DESC";
		} else if(sortOrderSetting != null && sortOrderSetting.equals("created_time")) {
			sortOrder = "created_on DESC";
		} else {
			sortOrder = DBConstants.DEFAULT_SORT_ORDER;
		}

        // Perform a managed query. The Activity will handle closing and requerying the cursor when needed.
        Cursor cursor = managedQuery(getIntent().getData(), PROJECTION, DBConstants.DELETED_FROM_PHONE + "!=1", null, sortOrder);

        // Used to map notes entries from the database to views
        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, getNotesListItemId(), cursor,
                new String[] { DBConstants.TITLE }, new int[] { android.R.id.text1 });

        //Set filter that will allow searching notes by typing over the list
        adapter.setFilterQueryProvider(new FilterQueryProvider() {

			@Override
			public Cursor runQuery(CharSequence constraint)
			{
				String constraintString = "" + constraint;
				String whereClause;
				String[] whereArgs;
				if(constraintString.contains("*"))
				{
					//'*' indicates search both title and contents
					constraintString = constraintString.replace("*", "");
					whereClause = DBConstants.DELETED_FROM_PHONE + "!=1 AND (" + DBConstants.TITLE + " LIKE ? OR " + DBConstants.CONTENTS + " LIKE ?)";
					whereArgs = new String[] { "%"+constraintString+"%", "%"+constraintString+"%" };
				}
				else
				{
					whereClause = DBConstants.DELETED_FROM_PHONE + "!=1 AND " + DBConstants.TITLE + " LIKE ?";
					whereArgs = new String[] { "%"+constraintString+"%" };
				}

				//Log.w("ben", "Query: " + constraint);
				return managedQuery(getIntent().getData(), PROJECTION, whereClause, whereArgs, sortOrder);
			}
		});
        setListAdapter(adapter);


	}

	@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);



        // This is our one standard application action -- inserting a
        // new note into the list.
        menu.add(0, MENU_ITEM_INSERT, 0, NotepadStrings.menu_insert)
                .setShortcut('1', 'a')
                .setIcon(android.R.drawable.ic_menu_add);

        // Sync with the server
        menu.add(0, MENU_ITEM_SYNC, 0, NotepadStrings.menu_sync)
                .setShortcut('2', 's')
                .setIcon(getSyncMenuIconId());
                //.setIcon(android.R.drawable.ic_menu_upload);

        // Settings
        menu.add(0, MENU_ITEM_SETTINGS, 0, NotepadStrings.menu_settings)
                .setShortcut('3', 'e')
                .setIcon(android.R.drawable.ic_menu_preferences);



        /*
        // Generate any additional actions that can be performed on the
        // overall list.  In a normal install, there are no additional
        // actions found here, but this allows other applications to extend
        // our menu with their own actions.
        Intent intent = new Intent(null, getIntent().getData());
        intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
        menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0,
                new ComponentName(this, NotesList.class), null, intent, 0, null);

         */
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);

        /*
        final boolean haveItems = getListAdapter().getCount() > 0;

        // If there are any notes in the list (which implies that one of
        // them is selected), then we need to generate the actions that
        // can be performed on the current selection.  This will be a combination
        // of our own specific actions along with any extensions that can be
        // found.
        if (haveItems) {
            // This is the selected item.
            Uri uri = ContentUris.withAppendedId(getIntent().getData(), getSelectedItemId());

            // Build menu...  always starts with the EDIT action...
            Intent[] specifics = new Intent[1];
            specifics[0] = new Intent(Intent.ACTION_EDIT, uri);
            MenuItem[] items = new MenuItem[1];

            // ... is followed by whatever other actions are available...
            Intent intent = new Intent(null, uri);
            intent.addCategory(Intent.CATEGORY_ALTERNATIVE);
            menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, 0, 0, null, specifics, intent, 0,
                    items);

            // Give a shortcut to the edit action.
            if (items[0] != null) {
                items[0].setShortcut('1', 'e');
            }
        } else {
            menu.removeGroup(Menu.CATEGORY_ALTERNATIVE);
        }

        */

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case MENU_ITEM_INSERT:
            // Launch activity to insert a new item
        	doEditNote(getIntent().getData(), Intent.ACTION_INSERT);
            return true;

        case MENU_ITEM_SYNC:
	       	// Launch activity to sync notes with the server
            doSync();
            return true;

        case MENU_ITEM_SETTINGS:
        	 // Launch preferences
            doPreferences();
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo menuInfo) {
        AdapterView.AdapterContextMenuInfo info;
        try {
             info = (AdapterView.AdapterContextMenuInfo) menuInfo;
        } catch (ClassCastException e) {
            Log.e(TAG, "bad menuInfo", e);
            return;
        }

        Cursor cursor = (Cursor) getListAdapter().getItem(info.position);
        if (cursor == null) {
            // For some reason the requested item isn't available, do nothing
            return;
        }

        // Setup the menu header
        menu.setHeaderTitle(cursor.getString(COLUMN_INDEX_TITLE));

        // Add a menu item to delete the note
        //menu.add(0, MENU_ITEM_EDIT, 0, NotepadStrings.menu_edit);
        menu.add(0, MENU_ITEM_EDIT_TITLE, 0, NotepadStrings.menu_edit_title);
        menu.add(0, MENU_ITEM_DELETE, 0, NotepadStrings.menu_delete);

    }

    @Override
    public boolean onContextItemSelected(MenuItem item) {
        AdapterView.AdapterContextMenuInfo info;
        try {
             info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
        } catch (ClassCastException e) {
            Log.e(TAG, "bad menuInfo", e);
            return false;
        }

        switch (item.getItemId()) {
	        case MENU_ITEM_EDIT: {
	        	Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
  	        	doEditNote(noteUri, Intent.ACTION_EDIT);
	        	return true;
	        }
            case MENU_ITEM_DELETE: {
                // Delete the note that the context menu is for
                Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
                //getContentResolver().delete(noteUri, null, null);
                UtilityMethods.markNoteForDeletion(this, noteUri);
                return true;
            }
            case MENU_ITEM_EDIT_TITLE: {
            	Uri noteUri = ContentUris.withAppendedId(getIntent().getData(), info.id);
            	doEditTitle(noteUri);
            	return true;
            }

        }
        return false;
    }

    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        Uri uri = ContentUris.withAppendedId(getIntent().getData(), id);

        String action = getIntent().getAction();
        if (Intent.ACTION_PICK.equals(action) || Intent.ACTION_GET_CONTENT.equals(action)) {
            // The caller is waiting for us to return a note selected by
            // the user.  The have clicked on one, so return it now.
            setResult(RESULT_OK, new Intent().setData(uri));
        } else {
            // Launch activity to view/edit the currently selected item
            doEditNote(uri, Intent.ACTION_EDIT);
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        super.onActivityResult(requestCode, resultCode, data);

        // The preferences returned if the request code is what we had given
        // earlier in startSubActivity
        if (requestCode == REQUEST_CODE_PREFERENCES) {
        	updateList();
        }
    }

    @Override
    protected void onPause() {

    	//------- LOCALYITCS -----
    	this.localyticsSession.close();
        //------- LOCALYITCS -----

    	super.onPause();
    }

    @Override
    protected void onDestroy()
    {
    	//------- LOCALYITCS -----
        this.localyticsSession.upload();
    	//------- LOCALYITCS -----

        super.onDestroy();
    }
}
